/*
	jGrouse framework
	Copyright 2007 by Denis Riabtchik 
	All rights reserved.
	
	Licensed under modified BSD license. See license.txt for details
*/

/**
	Browser Event manipulation routines.
	@module jgrouse.dom.Event
	@requires module-jgrouse.util.Maps
	@requires module-jgrouse.util.Sets
	@requires module-jgrouse.browser.Browser
	@requires module-jgrouse.dom.Element 
*/
jgrouse.module(
{
	name : 'jgrouse.dom.Event', 
	requires : ['jgrouse.util.Maps', 'jgrouse.util.Sets', 
		'jgrouse.browser.Browser', 'jgrouse.dom.Element'],
	imports : ['jgrouse.util.ObjectMap', 'jgrouse.util.ObjectSet'],
	body : function(embed)
	{
		eval(embed);
		var browser = jgrouse.browser.instance;
		
		function compare(item1, item2)
		{
			return (item1 === item2 || 
				(item1.eventName === item2.eventName 
				 && item1.listener === item2.listener 
				 && item1.doCapture === item2.doCapture));
		}
		
		if (!jgrouse.dom)
		{
			jgrouse.dom = {};
		}
	
		/**
			@namespace jgrouse.dom.Event
		*/
		jgrouse.dom.Event = 
		{
			_listenersCache : new ObjectMap(),
		
			/**
				Adds event listener to DOM element
				@function addListener
				@param {DOMElement} domElement - target node
				@param {String} eventName - name of event (like 'click', 'mousemove', etc)
				@param {jgrouse.browser.domEventHandler} listner - function to be triggered when event happens
				@param {boolean} doCapture - if listener should be added using "capture" semantics
			*/
			addListener : function(domElement, eventName, listener, doCapture)
			{
				doCapture |= false;
				var listeners = this._listenersCache.get(domElement);
				if (typeof listeners == 'undefined')
				{
					listeners = new ObjectSet(compare);
				}
				listeners.put({eventName : eventName, listener : listener, doCapture : doCapture});
				browser.addListener(domElement, eventName, listener, doCapture);
			},
			
			/**
				Remove event listener. Note - the parameters should be exactly the same as passed to addListener
				@function removeListener
				@param {DOMElement} domElement - target node
				@param {String} eventName - name of event
				@param {function(event)} listner - function to be triggered when event happens
				@param {boolean} doCapture - if listener should be added using "capture" semantics
			*/
			removeListener : function(domElement, eventName, listener, doCapture)
			{
				doCapture |= doCapture;
				var listeners = this._listenersCache.get(domElement);
				if (listeners)
				{
					var old = listeners.remove({eventName : eventName, listener : listener, doCapture : doCapture});
					browser.removeListener(domElement, eventName, listener, doCapture);
					return !!old;
				}
				return false;
			},
			
			/**
				Remove all event listeners from dom node
				@function removeElementListeners
				@param {DOMElement} domElement - target node
			*/
			removeElementListeners : function(domElement)
			{
				var listeners = this._listenersCache.get(domElement);
				if (listeners)
				{
					listeners.forEach(function(item)
					{
						browser.removeListener(domElement, item.eventName, item.listener, item.doCapture);
					})
					this._listenersCache.remove(domElement);
				}
			},
			/**
				Remove event listnerers from all elements
				@function removeAllListeners
			*/
			removeAllListeners : function()
			{
				var athis = this;
				this._listenersCache.forEach(function(key, value)
				{
					values.forEach(function(item)
					{
						browser.removeListener(key, item.eventName, item.listener, item.doCapture);
					});
				});
				this._listenersCache.clear();
			},
			
			cancelEvent : function(event)
			{
				browser.cancelEvent(event);
			}
		};
		
		function unloadAll()
		{
			jgrouse.dom.Event.removeAllListeners();
			for (var i = jgrouse._closeHooks.length - 1; i >= 0; i--)
			{
				jgrouse._closeHooks[i]();
			}
			jgrouse._closeHooks = [];
		}
		
		jgrouse.dom.Event.addListener(window, 'unload', unloadAll);
	}	
});
	 